home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / devel / vbcc-src / machines / ppc / schedule.c < prev    next >
C/C++ Source or Header  |  1999-01-01  |  30KB  |  1,138 lines

  1. /*
  2.  * vscppc
  3.  *
  4.  * vbcc PowerPC scheduler
  5.  * (C)1998 by Frank Wille <frank@phoenix.owl.de>
  6.  *
  7.  * vscppc is freeware and part of the portable and retargetable ANSI C
  8.  * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
  9.  * vscppc may be freely redistributed as long as no modifications are
  10.  * made and nothing is charged for it. Non-commercial usage is allowed
  11.  * without any restrictions.
  12.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  13.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  14.  *
  15.  * History:
  16.  * V0.3b  30-Jul-98
  17.  *        crxxx instructions used/modified wrong CCRs.
  18.  * V0.3a  21-Jul-98
  19.  *        "la" instruction was not recognized.
  20.  * V0.3   20-Jul-98
  21.  *        Target-specific options via sched_option() removed. Options
  22.  *        are passed in the assembler source, e.g. "#vsc elf".
  23.  *        Differentiation between 603 and 604 (selected by "#vsc cpu").
  24.  *        Now, scheduling takes place with regard to the real PowerPC
  25.  *        architecture.
  26.  * V0.2   12-Jul-98
  27.  *        Option "-elf" lets the scheduler accept ELF/SVR4 sources,
  28.  *        which only use numbers instead of full register names.
  29.  *        Target-specific options require a modification in the
  30.  *        portable scheduler part vsc.c.
  31.  * V0.1   10-Jul-98
  32.  *        vscppc seems to be stable, after some tests.
  33.  *        However, it still needs a lot of fine tuning (my PowerPC
  34.  *        docs are at home).
  35.  *        A differentiation between the PPC CPUs (603e, 604e) is missing.
  36.  * V0.0   09-Jul-98
  37.  *        File created.
  38.  *
  39.  */
  40.  
  41. #include "vsc.h"
  42.  
  43. char tg_copyright[]="PowerPC scheduler V0.3b (c) in 1998 by Frank Wille";
  44.  
  45. static int elf=0,cpu=604;
  46.  
  47.  
  48.  
  49. int sched_init(void)
  50. {
  51.   return (1);
  52. }
  53.  
  54.  
  55. void sched_cleanup(void)
  56. {
  57. }
  58.  
  59.  
  60. static void sched_option(char *s)
  61. {
  62.   if (!strncmp(s,"elf",3)) {
  63.     elf = 1;
  64.   }
  65.   else if (!strncmp(s,"cpu ",4)) {
  66.     if (!strncmp(s+4,"603",3))
  67.       cpu = 603;
  68.     else if (!strncmp(s+4,"604",3))
  69.       cpu = 604;
  70.   }
  71. }
  72.  
  73.  
  74. static char *strest(char *s,int n)
  75. /* returns ptr to the last n characters of string s */
  76. {
  77.   return (s + strlen(s) - n);
  78. }
  79.  
  80.  
  81. static int setlab(struct sinfo *p,char *lab)
  82. /* check for a valid local label */
  83. {
  84.   int i;
  85.  
  86.   if (sscanf(lab,elf?".l%d":"l%d",&i) == 1) {
  87.     p->label = i;
  88.     return (1);
  89.   }
  90.   return (0);
  91. }
  92.  
  93.  
  94. static int lsreg(char *s)
  95. /* checks the operand for load/store addressing mode and returns */
  96. /* the base register on success, -1 otherwise */
  97. {
  98.   char *p = (s+strlen(s))-1;
  99.   int q;
  100.  
  101.   while (p>s && *p!='(')
  102.     --p;
  103.   if (sscanf(p,elf?"(%d)":"(r%d)",&q) == 1)
  104.     return (q);
  105.   return (-1);
  106. }
  107.  
  108.  
  109. int sched_info(struct sinfo *p)
  110. {
  111.   char buf[16],oper[40],c;
  112.   int q1,q2,q3,z,i,x,n;
  113.  
  114.   /* check for vscppc specific options in the source */
  115.   if (!strncmp(p->txt,"#vsc ",5)) {
  116.     sched_option(p->txt+5);
  117.     p->flags = BARRIER;
  118.     return (1);
  119.   }
  120.  
  121.   if (!strncmp(p->txt,"#barrier",8)) {
  122.     /* an artificial barrier, used e.g. for inline-code */
  123.     p->flags = BARRIER;
  124.     return (1);
  125.   }
  126.  
  127.   if (sscanf(p->txt," .%15s %39s",buf,oper) >= 1) {
  128.     /* assembler directive or macro */
  129.     p->flags = BARRIER;
  130.     return (1);
  131.   }
  132.  
  133.   if (sscanf(p->txt,elf?".l%d:":"l%d:",&i) == 1) {
  134.     /* a local label */
  135.     p->label = i;
  136.     p->flags = LABEL;
  137.     return (1);
  138.   }
  139.  
  140.   if ((n = sscanf(p->txt," b%15s %39s",buf,oper)) >= 1) {
  141.     /* branch instruction */
  142.     p->latency = 1;
  143.     BSET(p->pipes,BPU);
  144.  
  145.     if (n == 1) {
  146.       /* branch unconditional: b label */
  147.       if (setlab(p,buf)) {
  148.         p->flags = UNCOND_BRANCH;
  149.         return (1);
  150.       }
  151.     }
  152.     else {
  153.       char *a = strest(buf,3);
  154.  
  155.       /* reject branch instructions ending with */
  156.       /* "lr", "ctr", "a" or "l", but accept "bnl" */
  157.       if ((strncmp(a+1,"lr",2) && strncmp(a,"ctr",3) &&
  158.            *(a+2)!='l' && *(a+2)!='a') ||
  159.           !strcmp(buf,"nl")) {
  160.  
  161.         if (*buf == 'd') {
  162.           /* bdz... or bdnz... */
  163.           a = oper;
  164.           if (strcmp(buf,"dz") && strcmp(buf,"dnz")) {
  165.             while (*a && *a!=',')
  166.               a++;
  167.             if (*a == ',')
  168.               a++;
  169.             else
  170.               a = 0;
  171.           }
  172.           if (a) {
  173.             if (setlab(p,a)) {
  174.               p->flags = COND_BRANCH;
  175.               BSET(p->modifies,CTR);
  176.               /* @@@ unable to determine the used CCRs - set all to used */
  177.               for (x=CCR; x<(CCR+8); x++)
  178.                 BSET(p->uses,x);
  179.               return (1);
  180.             }
  181.           }
  182.         }
  183.  
  184.         else if (*buf == 'c') {
  185.           if (sscanf(oper,"%d,%d,%s",&q1,&q2,buf) == 3) {
  186.             /* conditional branch: bc m,n,label */
  187.             if (setlab(p,buf)) {
  188.               p->flags = COND_BRANCH;
  189.               BSET(p->uses,CCR+(q2>>2));
  190.               return (1);
  191.             }
  192.           }
  193.         }
  194.  
  195.         else {
  196.           /* normal conditional branch: b<cond> [crN,]label */
  197.           a = buf;
  198.           if (sscanf(oper,elf?"%d,%s":"cr%d,%s",&i,buf) != 2) {
  199.             i = 0;
  200.             a = oper;
  201.           }
  202.           if (setlab(p,a)) {
  203.             p->flags = COND_BRANCH;
  204.             BSET(p->uses,CCR+i);
  205.             return (1);
  206.           }
  207.         }
  208.       }
  209.     }
  210.  
  211.     p->flags = BARRIER;
  212.     return (1);
  213.   }
  214.  
  215.  
  216.   if (cpu == 603) {
  217.     /* scheduling for the PowerPC 603 */
  218.  
  219.     if ((!elf && sscanf(p->txt," %15s %c%d,%39s",buf,&c,&z,oper) == 4) ||
  220.         (elf && sscanf(p->txt," %15s %d,%39s",buf,&z,oper) == 3)) {
  221.       if (elf) {
  222.         if ((buf[0]=='l' && buf[1]=='f') || (buf[0]=='s' && buf[2]=='f'))
  223.           c = 'f';
  224.         else
  225.           c = 'r';
  226.       }
  227.       if ((q1 = lsreg(oper))>=0 && (c=='r'||c=='f')) {
  228.         /* load/store instruction ...,d(rQ1) */
  229.  
  230.         if (!strcmp(buf,"la")) {
  231.           /* la rZ,d(rQ1) is the same as: addi rZ,rQ1,d */
  232.           p->latency = 1;
  233.           BSET(p->pipes,IU);
  234.           BSET(p->pipes,SRU);  /* addi may also execute in SRU */
  235.           BSET(p->uses,GPR+q1);
  236.           BSET(p->modifies,GPR+z);
  237.           return (1);
  238.         }
  239.  
  240.         BSET(p->pipes,LSU);
  241.         if (*(strest(buf,1)) == 'u')  /* update instruction? */
  242.           BSET(p->modifies,GPR+q1);
  243.         else
  244.           BSET(p->uses,GPR+q1);
  245.  
  246.         if (c == 'r') {
  247.           /* integer load/store */
  248.  
  249.           if (!strncmp(strest(buf,2),"mw",2)) {
  250.             /* load/store multiple word rz,i(rq1) */
  251.  
  252.             if (*buf == 'l') {
  253.               p->latency = 2+(32-z);
  254.               for (x=z; x<32; x++)
  255.                 BSET(p->modifies,GPR+x);
  256.               BSET(p->uses,MEM);
  257.             }
  258.             else {
  259.               p->latency = 1+(32-z);
  260.               for (x=z; x<32; x++)
  261.                 BSET(p->uses,GPR+x);
  262.               BSET(p->modifies,MEM);
  263.             }
  264.           }
  265.           else {
  266.             /* load/store integer rz,i(rq1) */
  267.  
  268.             p->latency = 3;
  269.             if(*buf == 'l') {
  270.               BSET(p->modifies,GPR+z);
  271.               BSET(p->uses,MEM);
  272.             }
  273.             else{
  274.               BSET(p->uses,GPR+z);
  275.               BSET(p->modifies,MEM);
  276.             }
  277.           }
  278.         }
  279.  
  280.         else {
  281.           /* load/store float fz,d(rQ1) */
  282.  
  283.           p->latency = 3;
  284.           if(*buf == 'l') {
  285.             BSET(p->modifies,FPR+z);
  286.             BSET(p->uses,MEM);
  287.           }
  288.           else{
  289.             BSET(p->uses,FPR+z);
  290.             BSET(p->modifies,MEM);
  291.           }
  292.         }
  293.  
  294.         return (1);
  295.       }
  296.     }
  297.  
  298.     if ((!elf && sscanf(p->txt," %15s %c%d,r%d,r%d",buf,&c,&z,&q1,&q2) == 5) ||
  299.         (elf && sscanf(p->txt," %15s %d,%d,%d",buf,&z,&q1,&q2) == 4)) {
  300.       if (*buf=='l' || (buf[0]=='s' && buf[1]=='t')) {
  301.         if (elf) {
  302.           if ((buf[0]=='l' && buf[1]=='f') || (buf[0]=='s' && buf[2]=='f'))
  303.             c = 'f';
  304.           else
  305.             c = 'r';
  306.         }
  307.  
  308.         BSET(p->pipes,LSU);
  309.         BSET(p->uses,GPR+q2);
  310.         if (!strncmp(strest(buf,2),"ux",2))  /* update instruction? */
  311.           BSET(p->modifies,GPR+q1);
  312.         else
  313.           BSET(p->uses,GPR+q1);
  314.  
  315.         if (c == 'r') {
  316.           /* integer load/store */
  317.  
  318.           if (!strncmp(buf,"lsw",3) || !strncmp(buf,"stsw",4)) {
  319.             /* load/store string word rz,rq1,rq2/imm */
  320.             p->flags = BARRIER;  /* too complex... ;) */
  321.             return (1);
  322.           }
  323.           else {
  324.             /* load/store integer indexed rz,rq1,rq2 */
  325.  
  326.             p->latency = 3;
  327.             if(*buf == 'l') {
  328.               BSET(p->modifies,GPR+z);
  329.               BSET(p->uses,MEM);
  330.             }
  331.             else{
  332.               if (!strcmp(buf,"stwcx."))
  333.                 p->latency = 8;
  334.               BSET(p->uses,GPR+z);
  335.               BSET(p->modifies,MEM);
  336.             }
  337.             return (1);
  338.           }
  339.         }
  340.  
  341.         else if (c == 'f') {
  342.           /* load/store float indexed fz,rq1,rq2 */
  343.           p->latency = 3;
  344.           if(*buf == 'l') {
  345.             BSET(p->modifies,FPR+z);
  346.             BSET(p->uses,MEM);
  347.           }
  348.           else{
  349.             BSET(p->uses,FPR+z);
  350.             BSET(p->modifies,MEM);
  351.           }
  352.           return (1);
  353.         }
  354.       }
  355.     }
  356.  
  357.     if (sscanf(p->txt,elf ? " fcm%15s %d,%d,%d" : " fcm%15s cr%d,f%d,f%d",
  358.                buf,&z,&q1,&q2) == 4) {
  359.       /* floating point compare */
  360.       p->latency = 3;
  361.       BSET(p->pipes,FPU);
  362.       BSET(p->modifies,CCR+z);
  363.       BSET(p->modifies,FPSCR);
  364.       BSET(p->uses,FPR+q1);
  365.       BSET(p->uses,FPR+q2);
  366.       return (1);
  367.     }
  368.     if (sscanf(p->txt,elf ? " fcm%15s %d,%d" : " fcm%15s f%d,f%d",
  369.                buf,&q1,&q2) == 3) {
  370.       /* floating point compare CR0 */
  371.       p->latency = 3;
  372.       BSET(p->pipes,FPU);
  373.       BSET(p->modifies,CCR);
  374.       BSET(p->modifies,FPSCR);
  375.       BSET(p->uses,FPR+q1);
  376.       BSET(p->uses,FPR+q2);
  377.       return (1);
  378.     }
  379.  
  380.     if ((n = sscanf(p->txt,elf ? " f%15s %d,%d,%d,%d" :
  381.                     " f%15s f%d,f%d,f%d,f%d",buf,&z,&q1,&q2,&q3))>=3) {
  382.       /* floating point operation with 2, 3 or 4 operands */
  383.  
  384.       if (strncmp(buf,"abs",3) &&
  385.           strncmp(buf,"mr",2) &&
  386.           strncmp(buf,"nabs",4) &&
  387.           strncmp(buf,"neg",3) &&
  388.           strncmp(buf,"sel",3))
  389.         BSET(p->modifies,FPSCR);  /* only some instr. doesn't alter FPSCR */
  390.  
  391.       if (!strncmp(buf,"divs",4) ||
  392.           !strncmp(buf,"res",3))
  393.         p->latency = 18;
  394.       else if (!strncmp(buf,"div",3))
  395.         p->latency = 33;
  396.       else if (!strncmp(buf,"mul",3) ||
  397.                !strncmp(buf,"madd",4) ||
  398.                !strncmp(buf,"msub",4) ||
  399.                !strncmp(buf,"nmadd",5) ||
  400.                !strncmp(buf,"nmsub",5))
  401.         p->latency = 4;
  402.       else
  403.         p->latency = 3;
  404.  
  405.       if (*(strest(buf,1)) == '.')
  406.         BSET(p->modifies,CCR+1);
  407.       BSET(p->pipes,FPU);
  408.       BSET(p->uses,FPR+q1);
  409.       if (n >= 4) {
  410.         BSET(p->uses,FPR+q2);
  411.         if (n == 5)
  412.           BSET(p->uses,FPR+q3);
  413.       }
  414.       BSET(p->modifies,FPR+z);
  415.       return (1);
  416.     }
  417.  
  418.     if (sscanf(p->txt,elf ? " cm%15s %d,%d,%d" : " cm%15s cr%d,r%d,r%d",
  419.         buf,&z,&q1,&q2) == 4) {
  420.       /* integer compare instruction */
  421.       p->latency = 1;
  422.       BSET(p->pipes,IU);
  423.       BSET(p->pipes,SRU);
  424.       BSET(p->modifies,CCR+z);
  425.       BSET(p->uses,GPR+q1);
  426.       if (*(strest(buf,1)) != 'i')
  427.         BSET(p->uses,GPR+q2);
  428.       return (1);
  429.     }
  430.     if (sscanf(p->txt,elf ? " cm%15s %d,%d" : " cm%15s r%d,r%d",
  431.         buf,&q1,&q2) == 3) {
  432.       /* integer compare instruction CR0 */
  433.       p->latency = 1;
  434.       BSET(p->pipes,IU);
  435.       BSET(p->pipes,SRU);
  436.       BSET(p->modifies,CCR);
  437.       BSET(p->uses,GPR+q1);
  438.       if (*(strest(buf,1)) != 'i')
  439.         BSET(p->uses,GPR+q2);
  440.       return (1);
  441.     }
  442.  
  443.     if (!elf) {
  444.       if (sscanf(p->txt," cm%15s cr%d,r%d,%d",buf,&z,&q1,&i) == 4) {
  445.         /* immediate integer compare instruction */
  446.         p->latency = 1;
  447.         BSET(p->pipes,IU);
  448.         BSET(p->pipes,SRU);
  449.         BSET(p->modifies,CCR+z);
  450.         BSET(p->uses,GPR+q1);
  451.         return (1);
  452.       }
  453.       if (sscanf(p->txt," cm%15s r%d,%d",buf,&q1,&i) == 3) {
  454.         /* immediate integer compare instruction CR0 */
  455.         p->latency = 1;
  456.         BSET(p->pipes,IU);
  457.         BSET(p->pipes,SRU);
  458.         BSET(p->modifies,CCR+z);
  459.         BSET(p->uses,GPR+q1);
  460.         return (1);
  461.       }
  462.     }
  463.  
  464.     if ((n = sscanf(p->txt," cr%15s %d,%d,%d",buf,&z,&q1,&q2)) >= 2) {
  465.       /* condition code register operation (vbcc uses this version) */
  466.       p->latency = 1;
  467.       BSET(p->pipes,SRU);
  468.       BSET(p->modifies,CCR+(z>>4));
  469.       if (n >= 3) {
  470.         BSET(p->uses,CCR+(q1>>4));
  471.         if (n == 4)
  472.           BSET(p->uses,CCR+(q2>>4));
  473.       }
  474.       return (1);
  475.     }
  476.  
  477.     if (sscanf(p->txt,elf ? " rlw%15s %d,%d,%d,%d,%d" :
  478.                " rlw%15s r%d,r%d,%d,%d,%d",buf,&z,&q1,&i,&n,&x) == 6) {
  479.       /* rotate left: rlwimi, rlwinm, rlwnm r1,r2,x,y,z */
  480.       p->latency = 1;
  481.       BSET(p->pipes,IU);
  482.       if (*(strest(buf,1)) == '.')
  483.         BSET(p->modifies,CCR);
  484.       BSET(p->uses,GPR+q1);
  485.       BSET(p->modifies,GPR+z);
  486.       return (1);
  487.     }
  488.  
  489.     if (sscanf(p->txt,elf ? " %15s %d,%d,%c" : " %15s r%d,r%d,%c",
  490.         buf,&z,&q1,&c) == 4) {
  491.       /* op r1,r2,imm */
  492.       if (!strncmp(buf,"addi",4) ||
  493.           !strncmp(buf,"andi",4) ||
  494.           !strncmp(buf,"mulli",5) ||
  495.           !strncmp(buf,"ori",3) ||
  496.           !strncmp(buf,"slwi",4) ||
  497.           !strncmp(buf,"srwi",4) ||
  498.           !strncmp(buf,"srawi",5) ||
  499.           !strncmp(buf,"subi",4) ||
  500.           !strncmp(buf,"xori",4)) {
  501.         char *a = strest(buf,1);
  502.  
  503.         if (*buf == 'm')  /* mulli */
  504.           p->latency = 3;
  505.         else
  506.           p->latency = 1;
  507.         BSET(p->pipes,IU);
  508.         if (!strncmp(buf,"add",3) && *(buf+4)!='c')
  509.           BSET(p->pipes,SRU);  /* addi/addis may also execute in SRU */
  510.         if (*a == '.') {
  511.           BSET(p->modifies,CCR);
  512.           --a;
  513.         }
  514.         if (*a == 'c')
  515.           BSET(p->modifies,XER);
  516.         BSET(p->uses,GPR+q1);
  517.         BSET(p->modifies,GPR+z);
  518.         return (1);
  519.       }
  520.     }
  521.  
  522.     if (sscanf(p->txt,elf ? " %15s %d,0,%d" : " %15s r%d,0,r%d",
  523.         buf,&z,&q2) == 3) {
  524.       /* op r1,0,r3 */
  525.       if (!strncmp(buf,"add",3) ||
  526.           !strncmp(buf,"sub",3)) {
  527.         p->latency = 1;
  528.         BSET(p->pipes,IU);
  529.         if (*(strest(buf,1)) == '.')
  530.           BSET(p->modifies,CCR);
  531.         else
  532.           BSET(p->pipes,SRU);  /* add/addo may also execute in SRU */
  533.         BSET(p->uses,GPR+q2);
  534.         BSET(p->modifies,GPR+z);
  535.         return (1);
  536.       }
  537.     }
  538.  
  539.     if (sscanf(p->txt,elf ? " %15s %d,%d,%d" : " %15s r%d,r%d,r%d",
  540.         buf,&z,&q1,&q2) == 4) {
  541.       /* op r1,r2,r3 */
  542.       if (!strncmp(buf,"add",3) ||
  543.           !strncmp(buf,"and",3) ||
  544.           !strncmp(buf,"div",3) ||
  545.           !strncmp(buf,"eqv",3) ||
  546.           !strncmp(buf,"mul",3) ||
  547.           !strncmp(buf,"nand",4) ||
  548.           !strncmp(buf,"nor",3) ||
  549.           !strncmp(buf,"or",2) ||
  550.           !strncmp(buf,"sl",2) ||
  551.           !strncmp(buf,"sr",2) ||
  552.           !strncmp(buf,"sub",3) ||
  553.           !strncmp(buf,"xor",3)) {
  554.         char *a = strest(buf,1);
  555.  
  556.         if (!strncmp(buf,"mul",3)) {
  557.           if (*(buf+5) == 'u')
  558.             p->latency = 6;  /* mulhwu needs 6 cycles */
  559.           else
  560.             p->latency = 5;
  561.           if (*(buf+3) == 'l')
  562.             BSET(p->modifies,XER);
  563.         }
  564.         else if (!strncmp(buf,"div",3)) {
  565.           p->latency = 37;
  566.           BSET(p->modifies,XER);
  567.         }
  568.         else
  569.           p->latency = 1;
  570.         BSET(p->pipes,IU);
  571.         if (!strcmp(buf,"add") || !strcmp(buf,"addo"))
  572.           BSET(p->pipes,SRU);  /* add/addo may also execute in SRU */
  573.  
  574.         if (*a == '.') {
  575.           BSET(p->modifies,CCR);
  576.           --a;
  577.         }
  578.         if (*a == 'o') {
  579.           BSET(p->modifies,XER);
  580.           --a;
  581.         }
  582.         if (*a == 'c') {
  583.           BSET(p->modifies,XER);
  584.           --a;
  585.         }
  586.         if (*a == 'e')
  587.           BSET(p->uses,XER);
  588.         BSET(p->uses,GPR+q1);
  589.         BSET(p->uses,GPR+q2);
  590.         BSET(p->modifies,GPR+z);
  591.         return (1);
  592.       }
  593.     }
  594.  
  595.     if (sscanf(p->txt,elf ? " l%15s %d,%c" : " l%15s r%d,%c",
  596.         buf,&z,&c) == 3) {
  597.       if (*buf == 'i') {
  598.         /* li, lis -> addi, addis */
  599.         p->latency = 1;
  600.         BSET(p->pipes,IU);
  601.         BSET(p->pipes,SRU);
  602.         BSET(p->modifies,GPR+z);
  603.         return (1);
  604.       }
  605.     }
  606.  
  607.     if (sscanf(p->txt,elf ? " %15s %d,%d" : " %15s r%d,r%d",
  608.         buf,&z,&q1) == 3) {
  609.       /* op r1,r2 */
  610.       if (!strncmp(buf,"add",3) ||
  611.           !strncmp(buf,"exts",4) ||
  612.           !strncmp(buf,"mr",2) ||
  613.           !strncmp(buf,"neg",3) ||
  614.           !strncmp(buf,"sub",3)) {
  615.         char *a = strest(buf,1);
  616.  
  617.         p->latency = 1;
  618.         if (*buf=='a' || *buf=='s')
  619.           BSET(p->uses,XER);  /* addme/addze/subfme/subfze/... */
  620.         BSET(p->pipes,IU);
  621.         if (*a == '.') {
  622.           BSET(p->modifies,CCR);
  623.           --a;
  624.         }
  625.         if (*a == 'o') {
  626.           BSET(p->modifies,XER);
  627.         }
  628.         BSET(p->uses,GPR+q1);
  629.         BSET(p->modifies,GPR+z);
  630.         return (1);
  631.       }
  632.     }
  633.  
  634.     if (sscanf(p->txt,elf?" m%15s %d":" m%15s r%d",buf,&z) == 2) {
  635.       /* mtxxx, mfxxx: move from/to special registers */
  636.       int reg=0;
  637.   
  638.       if (!strcmp(&buf[1],"xer"))
  639.         reg = XER;
  640.       else if (!strcmp(&buf[1],"ctr"))
  641.         reg = CTR;
  642.       else if (!strcmp(&buf[1],"lr"))
  643.         reg = LR;
  644.       else if (!strncmp(&buf[1],"fs",2))
  645.         reg = FPSCR;
  646.       if (reg) {
  647.         if (reg == FPSCR) {
  648.           p->latency = 3;
  649.           BSET(p->pipes,FPU);
  650.           if (*buf == 'f') {
  651.             BSET(p->uses,reg);
  652.             BSET(p->modifies,z);
  653.           }
  654.           else {
  655.             BSET(p->uses,z);
  656.             BSET(p->modifies,reg);
  657.           }
  658.         }
  659.         else {
  660.           BSET(p->pipes,SRU);
  661.           if (*buf == 'f') {
  662.             p->latency = 1;
  663.             BSET(p->uses,reg);
  664.             BSET(p->modifies,z);
  665.           }
  666.           else {
  667.             p->latency = 2;
  668.             BSET(p->uses,z);
  669.             BSET(p->modifies,reg);
  670.           }
  671.         }
  672.         return (1);
  673.       }
  674.     }
  675.   }
  676.  
  677.  
  678.   else if (cpu == 604) {
  679.     /* scheduling for the PowerPC 604 */
  680.  
  681.     if ((!elf && sscanf(p->txt," %15s %c%d,%39s",buf,&c,&z,oper) == 4) ||
  682.         (elf && sscanf(p->txt," %15s %d,%39s",buf,&z,oper) == 3)) {
  683.       if (elf) {
  684.         if ((buf[0]=='l' && buf[1]=='f') || (buf[0]=='s' && buf[2]=='f'))
  685.           c = 'f';
  686.         else
  687.           c = 'r';
  688.       }
  689.       if ((q1 = lsreg(oper))>=0 && (c=='r'||c=='f')) {
  690.         /* load/store instruction ...,d(rQ1) */
  691.  
  692.         if (!strcmp(buf,"la")) {
  693.           /* la rZ,d(rQ1) is the same as: addi rZ,rQ1,d */
  694.           p->latency = 1;
  695.           BSET(p->pipes,SCIU1);
  696.           BSET(p->pipes,SCIU2);
  697.           BSET(p->uses,GPR+q1);
  698.           BSET(p->modifies,GPR+z);
  699.           return (1);
  700.         }
  701.  
  702.         BSET(p->pipes,LSU);
  703.         if (*(strest(buf,1)) == 'u')  /* update instruction? */
  704.           BSET(p->modifies,GPR+q1);
  705.         else
  706.           BSET(p->uses,GPR+q1);
  707.  
  708.         if (c == 'r') {
  709.           /* integer load/store */
  710.  
  711.           if (!strncmp(strest(buf,2),"mw",2)) {
  712.             /* load/store multiple word rz,i(rq1) */
  713.  
  714.             p->latency = 2+(32-z);
  715.             if (*buf == 'l') {
  716.               for (x=z; x<32; x++)
  717.                 BSET(p->modifies,GPR+x);
  718.               BSET(p->uses,MEM);
  719.             }
  720.             else {
  721.               for (x=z; x<32; x++)
  722.                 BSET(p->uses,GPR+x);
  723.               BSET(p->modifies,MEM);
  724.             }
  725.           }
  726.           else {
  727.             /* load/store integer rz,i(rq1) */
  728.  
  729.             if(*buf == 'l') {
  730.               p->latency = 2;
  731.               BSET(p->modifies,GPR+z);
  732.               BSET(p->uses,MEM);
  733.             }
  734.             else{
  735.               p->latency = 3;
  736.               BSET(p->uses,GPR+z);
  737.               BSET(p->modifies,MEM);
  738.             }
  739.           }
  740.         }
  741.  
  742.         else {
  743.           /* load/store float fz,d(rQ1) */
  744.  
  745.           p->latency = 3;
  746.           if(*buf == 'l') {
  747.             BSET(p->modifies,FPR+z);
  748.             BSET(p->uses,MEM);
  749.           }
  750.           else{
  751.             BSET(p->uses,FPR+z);
  752.             BSET(p->modifies,MEM);
  753.           }
  754.         }
  755.  
  756.         return (1);
  757.       }
  758.     }
  759.  
  760.     if ((!elf && sscanf(p->txt," %15s %c%d,r%d,r%d",buf,&c,&z,&q1,&q2) == 5) ||
  761.         (elf && sscanf(p->txt," %15s %d,%d,%d",buf,&z,&q1,&q2) == 4)) {
  762.       if (*buf=='l' || (buf[0]=='s' && buf[1]=='t')) {
  763.         if (elf) {
  764.           if ((buf[0]=='l' && buf[1]=='f') || (buf[0]=='s' && buf[2]=='f'))
  765.             c = 'f';
  766.           else
  767.             c = 'r';
  768.         }
  769.  
  770.         BSET(p->pipes,LSU);
  771.         BSET(p->uses,GPR+q2);
  772.         if (!strncmp(strest(buf,2),"ux",2))  /* update instruction? */
  773.           BSET(p->modifies,GPR+q1);
  774.         else
  775.           BSET(p->uses,GPR+q1);
  776.  
  777.         if (c == 'r') {
  778.           /* integer load/store */
  779.  
  780.           if (!strncmp(buf,"lsw",3) || !strncmp(buf,"stsw",4)) {
  781.             /* load/store string word rz,rq1,rq2/imm */
  782.             p->flags = BARRIER;  /* too complex... ;) */
  783.             return (1);
  784.           }
  785.           else {
  786.             /* load/store integer indexed rz,rq1,rq2 */
  787.  
  788.             if(*buf == 'l') {
  789.               p->latency = 2;
  790.               BSET(p->modifies,GPR+z);
  791.               BSET(p->uses,MEM);
  792.             }
  793.             else{
  794.               p->latency = 3;
  795.               BSET(p->uses,GPR+z);
  796.               BSET(p->modifies,MEM);
  797.             }
  798.             return (1);
  799.           }
  800.         }
  801.  
  802.         else if (c == 'f') {
  803.           /* load/store float indexed fz,rq1,rq2 */
  804.           p->latency = 3;
  805.           if(*buf == 'l') {
  806.             BSET(p->modifies,FPR+z);
  807.             BSET(p->uses,MEM);
  808.           }
  809.           else{
  810.             BSET(p->uses,FPR+z);
  811.             BSET(p->modifies,MEM);
  812.           }
  813.           return (1);
  814.         }
  815.       }
  816.     }
  817.  
  818.     if (sscanf(p->txt,elf ? " fcm%15s %d,%d,%d" : " fcm%15s cr%d,f%d,f%d",
  819.                buf,&z,&q1,&q2) == 4) {
  820.       /* floating point compare */
  821.       p->latency = 3;
  822.       BSET(p->pipes,FPU);
  823.       BSET(p->modifies,CCR+z);
  824.       BSET(p->modifies,FPSCR);
  825.       BSET(p->uses,FPR+q1);
  826.       BSET(p->uses,FPR+q2);
  827.       return (1);
  828.     }
  829.     if (sscanf(p->txt,elf ? " fcm%15s %d,%d" : " fcm%15s f%d,f%d",
  830.                buf,&q1,&q2) == 3) {
  831.       /* floating point compare CR0 */
  832.       p->latency = 3;
  833.       BSET(p->pipes,FPU);
  834.       BSET(p->modifies,CCR);
  835.       BSET(p->modifies,FPSCR);
  836.       BSET(p->uses,FPR+q1);
  837.       BSET(p->uses,FPR+q2);
  838.       return (1);
  839.     }
  840.  
  841.     if ((n = sscanf(p->txt,elf ? " f%15s %d,%d,%d,%d" :
  842.                     " f%15s f%d,f%d,f%d,f%d",buf,&z,&q1,&q2,&q3))>=3) {
  843.       /* floating point operation with 2, 3 or 4 operands */
  844.  
  845.       if (strncmp(buf,"abs",3) &&
  846.           strncmp(buf,"mr",2) &&
  847.           strncmp(buf,"nabs",4) &&
  848.           strncmp(buf,"neg",3) &&
  849.           strncmp(buf,"sel",3))
  850.         BSET(p->modifies,FPSCR);  /* only some instr. doesn't alter FPSCR */
  851.  
  852.       if (!strncmp(buf,"divs",4) ||
  853.           !strncmp(buf,"res",3))
  854.         p->latency = 18;
  855.       else if (!strncmp(buf,"div",3))
  856.         p->latency = 32;
  857.       else
  858.         p->latency = 3;
  859.  
  860.       if (*(strest(buf,1)) == '.')
  861.         BSET(p->modifies,CCR+1);
  862.       BSET(p->pipes,FPU);
  863.       BSET(p->uses,FPR+q1);
  864.       if (n >= 4) {
  865.         BSET(p->uses,FPR+q2);
  866.         if (n == 5)
  867.           BSET(p->uses,FPR+q3);
  868.       }
  869.       BSET(p->modifies,FPR+z);
  870.       return (1);
  871.     }
  872.  
  873.     if (sscanf(p->txt,elf ? " cm%15s %d,%d,%d" : " cm%15s cr%d,r%d,r%d",
  874.         buf,&z,&q1,&q2) == 4) {
  875.       /* integer compare instruction */
  876.       p->latency = 1;
  877.       BSET(p->pipes,SCIU1);
  878.       BSET(p->pipes,SCIU2);
  879.       BSET(p->modifies,CCR+z);
  880.       BSET(p->uses,GPR+q1);
  881.       if (*(strest(buf,1)) != 'i')
  882.         BSET(p->uses,GPR+q2);
  883.       return (1);
  884.     }
  885.     if (sscanf(p->txt,elf ? " cm%15s %d,%d" : " cm%15s r%d,r%d",
  886.         buf,&q1,&q2) == 3) {
  887.       /* integer compare instruction CR0 */
  888.       p->latency = 1;
  889.       BSET(p->pipes,SCIU1);
  890.       BSET(p->pipes,SCIU2);
  891.       BSET(p->modifies,CCR);
  892.       BSET(p->uses,GPR+q1);
  893.       if (*(strest(buf,1)) != 'i')
  894.         BSET(p->uses,GPR+q2);
  895.       return (1);
  896.     }
  897.  
  898.     if (!elf) {
  899.       if (sscanf(p->txt," cm%15s cr%d,r%d,%d",buf,&z,&q1,&i) == 4) {
  900.         /* immediate integer compare instruction */
  901.         p->latency = 1;
  902.         BSET(p->pipes,SCIU1);
  903.         BSET(p->pipes,SCIU2);
  904.         BSET(p->modifies,CCR+z);
  905.         BSET(p->uses,GPR+q1);
  906.         return (1);
  907.       }
  908.       if (sscanf(p->txt," cm%15s r%d,%d",buf,&q1,&i) == 3) {
  909.         /* immediate integer compare instruction CR0 */
  910.         p->latency = 1;
  911.         BSET(p->pipes,SCIU1);
  912.         BSET(p->pipes,SCIU2);
  913.         BSET(p->modifies,CCR+z);
  914.         BSET(p->uses,GPR+q1);
  915.         return (1);
  916.       }
  917.     }
  918.  
  919.     if ((n = sscanf(p->txt," cr%15s %d,%d,%d",buf,&z,&q1,&q2)) >= 2) {
  920.       /* condition code register operation (vbcc uses this version) */
  921.       p->latency = 1;
  922.       BSET(p->pipes,CRU);
  923.       BSET(p->modifies,CCR+(z>>4));
  924.       if (n >= 3) {
  925.         BSET(p->uses,CCR+(q1>>4));
  926.         if (n == 4)
  927.           BSET(p->uses,CCR+(q2>>4));
  928.       }
  929.       return (1);
  930.     }
  931.  
  932.     if (sscanf(p->txt,elf ? " rlw%15s %d,%d,%d,%d,%d" :
  933.                " rlw%15s r%d,r%d,%d,%d,%d",buf,&z,&q1,&i,&n,&x) == 6) {
  934.       /* rotate left: rlwimi, rlwinm, rlwnm r1,r2,x,y,z */
  935.       p->latency = 1;
  936.       BSET(p->pipes,SCIU1);
  937.       BSET(p->pipes,SCIU2);
  938.       if (*(strest(buf,1)) == '.')
  939.         BSET(p->modifies,CCR);
  940.       BSET(p->uses,GPR+q1);
  941.       BSET(p->modifies,GPR+z);
  942.       return (1);
  943.     }
  944.  
  945.     if (sscanf(p->txt,elf ? " %15s %d,%d,%c" : " %15s r%d,r%d,%c",
  946.         buf,&z,&q1,&c) == 4) {
  947.       /* op r1,r2,imm */
  948.       if (!strncmp(buf,"addi",4) ||
  949.           !strncmp(buf,"andi",4) ||
  950.           !strncmp(buf,"mulli",5) ||
  951.           !strncmp(buf,"ori",3) ||
  952.           !strncmp(buf,"slwi",4) ||
  953.           !strncmp(buf,"srwi",4) ||
  954.           !strncmp(buf,"srawi",5) ||
  955.           !strncmp(buf,"subi",4) ||
  956.           !strncmp(buf,"xori",4)) {
  957.         char *a = strest(buf,1);
  958.  
  959.         if (*buf == 'm') { /* mulli */
  960.           p->latency = 3;
  961.           BSET(p->pipes,MCIU);
  962.         }
  963.         else {
  964.           p->latency = 1;
  965.           BSET(p->pipes,SCIU1);
  966.           BSET(p->pipes,SCIU2);
  967.         }
  968.         if (*a == '.') {
  969.           BSET(p->modifies,CCR);
  970.           --a;
  971.         }
  972.         if (*a == 'c')
  973.           BSET(p->modifies,XER);
  974.         BSET(p->uses,GPR+q1);
  975.         BSET(p->modifies,GPR+z);
  976.         return (1);
  977.       }
  978.     }
  979.  
  980.     if (sscanf(p->txt,elf ? " %15s %d,0,%d" : " %15s r%d,0,r%d",
  981.         buf,&z,&q2) == 3) {
  982.       /* op r1,0,r3 */
  983.       if (!strncmp(buf,"add",3) ||
  984.           !strncmp(buf,"sub",3)) {
  985.         p->latency = 1;
  986.         BSET(p->pipes,SCIU1);
  987.         BSET(p->pipes,SCIU2);
  988.         if (*(strest(buf,1)) == '.')
  989.           BSET(p->modifies,CCR);
  990.         else
  991.           BSET(p->pipes,SRU);  /* add/addo may also execute in SRU */
  992.         BSET(p->uses,GPR+q2);
  993.         BSET(p->modifies,GPR+z);
  994.         return (1);
  995.       }
  996.     }
  997.  
  998.     if (sscanf(p->txt,elf ? " %15s %d,%d,%d" : " %15s r%d,r%d,r%d",
  999.         buf,&z,&q1,&q2) == 4) {
  1000.       /* op r1,r2,r3 */
  1001.       if (!strncmp(buf,"add",3) ||
  1002.           !strncmp(buf,"and",3) ||
  1003.           !strncmp(buf,"div",3) ||
  1004.           !strncmp(buf,"eqv",3) ||
  1005.           !strncmp(buf,"mul",3) ||
  1006.           !strncmp(buf,"nand",4) ||
  1007.           !strncmp(buf,"nor",3) ||
  1008.           !strncmp(buf,"or",2) ||
  1009.           !strncmp(buf,"sl",2) ||
  1010.           !strncmp(buf,"sr",2) ||
  1011.           !strncmp(buf,"sub",3) ||
  1012.           !strncmp(buf,"xor",3)) {
  1013.         char *a = strest(buf,1);
  1014.  
  1015.         if (!strncmp(buf,"mul",3)) {
  1016.           p->latency = 4;
  1017.           BSET(p->pipes,MCIU);
  1018.           if (*(buf+3) == 'l')
  1019.             BSET(p->modifies,XER);
  1020.         }
  1021.         else if (!strncmp(buf,"div",3)) {
  1022.           p->latency = 20;
  1023.           BSET(p->pipes,MCIU);
  1024.           BSET(p->modifies,XER);
  1025.         }
  1026.         else {
  1027.           p->latency = 1;
  1028.           BSET(p->pipes,SCIU1);
  1029.           BSET(p->pipes,SCIU2);
  1030.         }
  1031.         if (*a == '.') {
  1032.           BSET(p->modifies,CCR);
  1033.           --a;
  1034.         }
  1035.         if (*a == 'o') {
  1036.           BSET(p->modifies,XER);
  1037.           --a;
  1038.         }
  1039.         if (*a == 'c') {
  1040.           BSET(p->modifies,XER);
  1041.           --a;
  1042.         }
  1043.         if (*a == 'e')
  1044.           BSET(p->uses,XER);
  1045.         BSET(p->uses,GPR+q1);
  1046.         BSET(p->uses,GPR+q2);
  1047.         BSET(p->modifies,GPR+z);
  1048.         return (1);
  1049.       }
  1050.     }
  1051.  
  1052.     if (sscanf(p->txt,elf ? " l%15s %d,%c" : " l%15s r%d,%c",
  1053.         buf,&z,&c) == 3) {
  1054.       if (*buf == 'i') {
  1055.         /* li, lis -> addi, addis */
  1056.         p->latency = 1;
  1057.         BSET(p->pipes,SCIU1);
  1058.         BSET(p->pipes,SCIU2);
  1059.         BSET(p->modifies,GPR+z);
  1060.         return (1);
  1061.       }
  1062.     }
  1063.  
  1064.     if (sscanf(p->txt,elf ? " %15s %d,%d" : " %15s r%d,r%d",
  1065.         buf,&z,&q1) == 3) {
  1066.       /* op r1,r2 */
  1067.       if (!strncmp(buf,"add",3) ||
  1068.           !strncmp(buf,"exts",4) ||
  1069.           !strncmp(buf,"mr",2) ||
  1070.           !strncmp(buf,"neg",3) ||
  1071.           !strncmp(buf,"sub",3)) {
  1072.         char *a = strest(buf,1);
  1073.  
  1074.         p->latency = 1;
  1075.         BSET(p->pipes,SCIU1);
  1076.         BSET(p->pipes,SCIU2);
  1077.         if (*buf=='a' || *buf=='s')
  1078.           BSET(p->uses,XER);  /* addme/addze/subfme/subfze/... */
  1079.         if (*a == '.') {
  1080.           BSET(p->modifies,CCR);
  1081.           --a;
  1082.         }
  1083.         if (*a == 'o') {
  1084.           BSET(p->modifies,XER);
  1085.         }
  1086.         BSET(p->uses,GPR+q1);
  1087.         BSET(p->modifies,GPR+z);
  1088.         return (1);
  1089.       }
  1090.     }
  1091.  
  1092.     if (sscanf(p->txt,elf?" m%15s %d":" m%15s r%d",buf,&z) == 2) {
  1093.       /* mtxxx, mfxxx: move from/to special registers */
  1094.       int reg=0;
  1095.   
  1096.       if (!strcmp(&buf[1],"xer"))
  1097.         reg = XER;
  1098.       else if (!strcmp(&buf[1],"ctr"))
  1099.         reg = CTR;
  1100.       else if (!strcmp(&buf[1],"lr"))
  1101.         reg = LR;
  1102.       else if (!strncmp(&buf[1],"fs",2))
  1103.         reg = FPSCR;
  1104.       if (reg) {
  1105.         if (reg == FPSCR) {
  1106.           p->latency = 3;
  1107.           BSET(p->pipes,FPU);
  1108.           if (*buf == 'f') {
  1109.             BSET(p->uses,reg);
  1110.             BSET(p->modifies,z);
  1111.           }
  1112.           else {
  1113.             BSET(p->uses,z);
  1114.             BSET(p->modifies,reg);
  1115.           }
  1116.         }
  1117.         else {
  1118.           BSET(p->pipes,MCIU);
  1119.           if (*buf == 'f') {
  1120.             p->latency = 3;
  1121.             BSET(p->uses,reg);
  1122.             BSET(p->modifies,z);
  1123.           }
  1124.           else {
  1125.             p->latency = 1;
  1126.             BSET(p->uses,z);
  1127.             BSET(p->modifies,reg);
  1128.           }
  1129.         }
  1130.         return (1);
  1131.       }
  1132.     }
  1133.   }
  1134.  
  1135.   p->flags = BARRIER;
  1136.   return (1);
  1137. }
  1138.